package com.bailiban.aop;

import com.bailiban.controller.OrdersController;
import com.bailiban.entity.Syslog;
import com.bailiban.service.SyslogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.annotation.security.RolesAllowed;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author zhulang
 * @Classname SysLogAspect
 * @Description SysLogAspect
 */
@Aspect
@Component
public class SysLogAspect {
    private Class aClass;
    private Method method;
    private Date visittime;
    private Integer executionTime;
    private String className;
    private String methodName;
    private String url;
    private String ip;

    @Autowired
    private SyslogService syslogService;
    @Autowired
    private HttpServletRequest request;

    @Pointcut("execution(* com.bailiban.controller.*.*(..))")
    public void pointcut() {

    }

    @Pointcut("execution(* com.bailiban.controller.SysLogController.*(..))")
    public void pointcut1() {

    }

    @Pointcut("pointcut()&&!pointcut1()")
    public void pointcut2() {

    }

    /**
     * 前置通知
     *
     * @param jp
     */
    @Before("pointcut2()")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        //访问时间
        visittime = new Date();
//       com.bailiban.controller.OrdersController.findAll()
        aClass = jp.getTarget().getClass();
        className = aClass.getName();
        String typeName = aClass.getTypeName();
        System.out.println("className:" + className);
        System.out.println("typeName:" + typeName);
        methodName = jp.getSignature().getName();
        System.out.println("methodName:" + methodName);
        Object[] args = jp.getArgs();
        if (args == null || args.length == 0) {
//无参构造
            method = aClass.getMethod(methodName);
        } else {
            Class[] classes = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                classes[i] = args[i].getClass();
            }
            method = aClass.getMethod(methodName, classes);
        }

    }

    /**
     * 后置通知
     *
     * @param jp
     */
    @After("pointcut2()")
    public void doAfter(JoinPoint jp) {
        Date endDate = new Date();
        executionTime = (int) (endDate.getTime() - visittime.getTime());
//        获取访问的ip
        String remoteAddr = request.getRemoteAddr();
//        获取访问 用户
        String name = request.getUserPrincipal().getName();
//        获取类上的RequestMapping注解
        RequestMapping annotationClass = (RequestMapping) aClass.getAnnotation(RequestMapping.class);
        String classPath = annotationClass.value()[0];
        Annotation[] methodAnnotations = method.getAnnotations();
        //找到Mapping结尾的注解
        String methodPath = "";
        for (int i = 0; i < methodAnnotations.length; i++) {

//           GetMapping
//            RolesAllowed
            String simpleName = methodAnnotations[i].annotationType().getSimpleName();
            if (simpleName.contains("Mapping")) {
                methodPath = getMethodPath(simpleName);
            }

        }
        url = classPath + "/" + methodPath;
        Syslog syslog = new Syslog();
        syslog.setExecutiontime(executionTime);
        syslog.setIp(remoteAddr);
        syslog.setMethod("类-" + className + "-方法-" + methodName);
        syslog.setUrl(url);
        syslog.setUsername(name);
        syslog.setVisittime(visittime);
        syslogService.insert(syslog);
    }

    public String getMethodPath(String methodAnnotationName) {
        String path = "";
        switch (methodAnnotationName) {
            case "RequestMapping":
                RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                path = annotation.value()[0];
                break;
            case "PostMapping":
                PostMapping annotation1 = method.getAnnotation(PostMapping.class);
                path = annotation1.value()[0];
                break;
            case "GetMapping":
                GetMapping annotation2 = method.getAnnotation(GetMapping.class);
                path = annotation2.value()[0];
                break;
            case "PutMapping":
                PutMapping annotation3 = method.getAnnotation(PutMapping.class);
                path = annotation3.value()[0];
                break;
            case "DeleteMapping":
                DeleteMapping annotation4 = method.getAnnotation(DeleteMapping.class);
                path = annotation4.value()[0];
                break;
        }
        return path;
    }
}
